home *** CD-ROM | disk | FTP | other *** search
- /*
- File: UnitTableFloppySupport.c
-
- Contains: All floppy disk specific functionality
-
- Version: 1.0
-
- Copyright: © 1998-1999 by Apple Computer, Inc., all rights reserved.
-
- */
- #include <DriverServices.h>
- #include <Errors.h>
-
- #include "UnitTableFloppySupport.h"
- #include "UnitTableDeviceAccess.h"
- #include "UnitTableDriveQSupport.h"
- #include "UnitTableCWDefines.h"
-
- typedef struct FloppyRequestPB
- {
- UInt32 userData;
- ControlStatusCompletionProcPtr completionProc;
- } FloppyRequestPB, *FloppyRequestPBPtr;
-
-
- static DriveQRecPtr gFloppyDrive = nil;
- static FloppyRequestPB gFloppyInternalDrivePB;
-
- static OSStatus FormatFloppyDisk(FloppyRequestPB *drivePB);
- static OSStatus VerifyFloppyDisk( FloppyRequestPB *drivePB );
- static OSStatus FormatAndWriteFloppyImage( CntrlParamPtr pbPtr );
- static OSStatus GetFloppyFormatList( CntrlParamPtr pbPtr );
-
- static volatile OSStatus gInternalReadWriteErr;
- static void InternalReadWriteCompletion( UInt32 userData, OSStatus status );
-
- void ResetFloppyDriveQueue( DriveQRecPtr floppyDriveQ )
- {
- DrvSts *theDriveStatus;
-
- theDriveStatus = (DrvSts *) &floppyDriveQ->driveStatus;
-
- theDriveStatus->track = 80; // Sectors on a MFM disk
- theDriveStatus->writeProt = 0; // not write protected yet
- theDriveStatus->diskInPlace = 0; // Ejectable Disk
- theDriveStatus->installed = 1; // drive is installed
- theDriveStatus->sides = -1; // -1 means double sided floppy
- theDriveStatus->qType = 0; // neither dQDrvSz and dQDrvSz2 are used
- theDriveStatus->dQFSID = 0; // File Manager's volume type
- theDriveStatus->twoSideFmt = -1; /* after 1st rd/wrt: 0=1 side, -1=2 side */
- theDriveStatus->needsFlush = -1; /* -1 for MacPlus drive */
- theDriveStatus->diskErrs = 0; /* soft error count */
- }
-
- DriveQRecPtr GetFloppyDriveRec( void )
- {
- return gFloppyDrive;
- }
-
- Boolean IsDriveAFloppy( SInt16 driveRefNum )
- {
- if (gFloppyDrive == nil )
- {
- return false;
- }
-
- if ( gFloppyDrive->driveNum == driveRefNum )
- {
- return true;
- }
- else
- {
- return false;
- }
- }
-
- OSStatus SetupFloppyStructures( SInt16 theDrvrRefNum )
- {
- gFloppyDrive = GetNewDriveQRec();
-
- ResetFloppyDriveQueue( gFloppyDrive );
-
- gFloppyDrive->deviceType = kdgFloppyType;
- gFloppyDrive->isFloppy = true;
- gFloppyDrive->isValidRecord = false;
- gFloppyDrive->isPermanentQElement = true;
-
- if( IsDriveQueueNumberFree( 1 ) == true )
- {
- // Drive queue element 1 is free, use it
- gFloppyDrive->driveNum = 1; // assign a logical drive number
- }
- else if( IsDriveQueueNumberFree( 2 ) == true )
- {
- // Drive queue element 2 is free, use it
- gFloppyDrive->driveNum = 2; // assign a logical drive number
- }
- else
- {
- gFloppyDrive->driveNum = NextQDrive(); // assign a logical drive number
- }
-
- NativeAddDrive(theDrvrRefNum, gFloppyDrive->driveNum, (DrvQElPtr) &gFloppyDrive->driveStatus.qLink);
-
- return noErr;
- }
-
- OSStatus RemoveFloppyStructures( void )
- {
- if ( gFloppyDrive != nil )
- {
- // If we installed a floppy drive Queue, remove it.
- RemoveDrive( gFloppyDrive );
- }
-
- return noErr;
- }
-
- OSStatus FloppyControlCallSupport( UInt32 userData,
- CntrlParamPtr cntrlPBPtr,
- ControlStatusCompletionProcPtr callBack )
- {
- OSStatus err = noErr;
- SInt16 driveNum;
-
- BlockZero((Ptr) &gFloppyInternalDrivePB, sizeof(FloppyRequestPB));
-
- gFloppyInternalDrivePB.userData = userData;
- gFloppyInternalDrivePB.completionProc = callBack;
-
- driveNum = cntrlPBPtr->ioVRefNum;
-
- // Parse the control codes…
- switch( cntrlPBPtr->csCode )
- {
- case kVerify: // Verify the media, this should only be called for floppies
- {
- err = VerifyFloppyDisk( &gFloppyInternalDrivePB );
- }
- break;
-
- case kFormat:
- {
- err = FormatFloppyDisk( &gFloppyInternalDrivePB );
- }
- break;
-
- case kSetTagBuffer: // This is a floppy specific control call
- {
- err = controlErr; // Return a controlErr, since we do not support this call
- }
- break;
-
- case kTrackCache: // This is a floppy specific control call
- {
- err = noErr; // The driver does not keep an internal write cache,
- // therefore, it will act like it does and return noErr
- }
- break;
-
- case kDriveInfo: // DRIVE INFO request (was from ATA maanger)
- {
- // If we currently have a floppy loaded, return the following info
- cntrlPBPtr->csParam[1] = ( 1 << 11 ) // Drive cardinality (0 - primary, 1 - secondary)
- | ( 0 << 10 ) // Media removability ( 0 - removable, 1 - fixed )
- | ( 0 << 9 ) // Interface ( 0 - floppy, 1 - SCSI )
- | ( 1 << 8 ) // Location ( 0 - internal, 1 - external )
- // Bits 4,5,6,7 are reserved
- | 4; // Drive Type ( use 4 for SuperDrive for compatibility )
- }
- break;
-
- // Floppy specific call to support the DiskCopy Format and Write Image function
- case kDiskCopy:
- {
- err = FormatAndWriteFloppyImage( cntrlPBPtr );
- }
- break;
-
- default:
- {
- err = controlErr;
- }
- break;
- }
-
- return err;
- }
-
- OSStatus FloppyStatusCallSupport( UInt32 userData,
- CntrlParamPtr cntrlPBPtr,
- ControlStatusCompletionProcPtr callBack )
- {
- OSStatus err = noErr;
- SInt16 driveNum;
-
- BlockZero((Ptr) &gFloppyInternalDrivePB, sizeof(FloppyRequestPB));
- gFloppyInternalDrivePB.userData = userData;
- gFloppyInternalDrivePB.completionProc = callBack;
-
- driveNum = cntrlPBPtr->ioVRefNum;
-
- // Parse the control codes…
- switch(cntrlPBPtr->csCode)
- {
- case kReturnFormatList:
- {
- err = GetFloppyFormatList( cntrlPBPtr );
- }
- break;
-
- case kMFMStatus:
- {
- cntrlPBPtr->csParam[0] = -3; // PC Industry standard MFM (no GCR support)
-
- // Check to see if there is a floppy disk mounted
- if(GetFloppyDriveRec()->capacity != 0)
- {
- cntrlPBPtr->csParam[1] = -1; // MFM Disk installed
-
- if( GetFloppyDriveRec()->capacity < 0x600 )
- {
- cntrlPBPtr->csParam[2] = 0; // 720K MFM Disk installed
- }
- else
- {
- cntrlPBPtr->csParam[2] = -1; // 1.44M MFM Disk installed
- }
- }
- else
- {
- cntrlPBPtr->csParam[1] = 0; // No disk installed
- cntrlPBPtr->csParam[2] = 1; // No disk installed
- }
-
- cntrlPBPtr->csParam[3] = -5; // Generic PC Floppy Disk Controller
-
- err = noErr;
- }
- break;
-
- case kDuplicatorVersion: // DiskCopy version supported
- {
- cntrlPBPtr->csParam[0] = 0x0410; // We support the Diskcopy 4.1 API
- err = noErr;
- }
- break;
-
- default:
- {
- err = statusErr;
- }
- break;
- }
-
- return err;
- }
-
- OSStatus VerifyFloppyDisk( FloppyRequestPB *drivePB )
- {
- UInt16 diskCapacity;
- UInt16 startBlock;
- UInt16 numberBlocks = 16;
- UInt8 *blockBuffer;
- OSStatus err;
- DriveQRec *theDrive = gFloppyDrive;
-
- diskCapacity = theDrive->capacity;
- blockBuffer = (UInt8 *) NewPtrSysClear(numberBlocks * theDrive->blockSize);
- if(blockBuffer == nil)
- {
- err = verErr;
- }
- else
- {
- for (startBlock = 0; startBlock<diskCapacity; startBlock+=numberBlocks)
- {
- err = ReadWriteSingleBuffer( (UInt32) drivePB,
- startBlock,
- numberBlocks,
- (Ptr) blockBuffer,
- (numberBlocks * theDrive->blockSize),
- false,
- &InternalReadWriteCompletion );
-
- gInternalReadWriteErr = err;
-
- while ( err == 1 )
- {
- err = gInternalReadWriteErr;
- }
-
- // an Error has occured
- if ( err != noErr )
- {
- // report a verify error
- err = verErr;
- }
- }
-
- DisposePtr((Ptr) blockBuffer);
- }
-
- return err;
- }
-
- OSStatus FormatAndWriteFloppyImage( CntrlParamPtr pbPtr )
- {
- UInt16 theFormat;
- UInt8 *theDiskImage;
- OSStatus err;
- DriveQRec *theDrive = gFloppyDrive;
-
- if( theDrive->isWriteProtected == true)
- {
- return wPrErr; // disk is write protected
- }
-
- theFormat = pbPtr->csParam[0];
- theDiskImage = (UInt8 *) *((UInt32 *) &pbPtr->csParam[1]); // Extract the pointer to the data
-
- err = ReadWriteSingleBuffer( (UInt32) nil,
- 0,
- theDrive->capacity,
- (Ptr) theDiskImage,
- (theDrive->capacity * theDrive->blockSize),
- true,
- &InternalReadWriteCompletion );
-
- gInternalReadWriteErr = err;
- while ( err == 1 )
- {
- err = gInternalReadWriteErr;
- }
-
- // an Error has occured
- if ( err != noErr )
- {
- // report an error
- err = paramErr;
- }
-
- return err;
- }
-
- OSStatus GetFloppyFormatList( CntrlParamPtr pbPtr )
- {
- typedef struct FormatList
- {
- UInt32 NumberBlock;
- UInt8 TSSValid : 1;
- UInt8 IsCurrentFormat : 1;
- UInt8 CanFormat : 1;
- UInt8 Density : 1;
- UInt8 NoSides : 4;
- UInt8 SecPerTrack;
- UInt16 NumberTracks;
- } FormatList;
-
- DriveQRec *theDrive;
- UInt8 returnNumber;
- UInt8 totalFormats = 2;
- FormatList theFormats[2];
-
- theDrive = gFloppyDrive;
-
- // Setup the Formats
- // Double Density Floppy Disk
- theFormats[0].NumberBlock = 1440;
- theFormats[0].TSSValid = 1;
- theFormats[0].Density = 0; // 0 means single density, 1 means Double Density
- theFormats[0].NoSides = 2;
- theFormats[0].SecPerTrack = 9;
- theFormats[0].NumberTracks = 80;
-
- // High Density Floppy Disk
- theFormats[1].NumberBlock = 2880;
- theFormats[1].TSSValid = 1;
- theFormats[1].Density = 1;
- theFormats[1].NoSides = 2;
- theFormats[1].SecPerTrack = 18;
- theFormats[1].NumberTracks = 80;
-
- if( theDrive->capacity == 0 )
- {
- // Ther is currently no disk mounted
- theFormats[0].CanFormat = 1; // 1 means we can not format this disk as 720K
- theFormats[1].CanFormat = 1; // 1 means we can not format this disk as 1.44M
- theFormats[0].IsCurrentFormat = 0; // 0 means 720K MFM Disk is not installed
- theFormats[1].IsCurrentFormat = 0; // 0 means 1.44M MFM Disk is not installed
- }
- else if( theDrive->capacity < 0x600 )
- {
- theFormats[0].CanFormat = 0; // 0 means we can format this disk as 720K
- theFormats[1].CanFormat = 1; // 1 means we can not format this disk as 1.44M
- theFormats[0].IsCurrentFormat = 1; // 1 means 720K MFM Disk is installed
- theFormats[1].IsCurrentFormat = 0; // 0 means 1.44M MFM Disk is not installed
- }
- else
- {
- theFormats[0].CanFormat = 1; // 1 means we can not format this disk as 720K
- theFormats[1].CanFormat = 0; // 0 means we can format this disk as 1.44M
- theFormats[0].IsCurrentFormat = 0; // 0 means 720K MFM Disk is not installed
- theFormats[1].IsCurrentFormat = 1; // 1 means 1.44M MFM Disk is installed
- }
-
- returnNumber = *((UInt16 *) &pbPtr->csParam[0]);
- if( totalFormats < returnNumber )
- {
- returnNumber = totalFormats;
- }
-
- BlockCopy( (Ptr) &theFormats[0], (Ptr) (*((UInt32 *) &pbPtr->csParam[1])), sizeof(FormatList) * returnNumber);
- *((UInt16 *) &pbPtr->csParam[0]) = returnNumber;
-
- return noErr;
- }
-
-
- void InternalReadWriteCompletion( UInt32 userData, OSStatus status )
- {
- #pragma unused ( userData )
- gInternalReadWriteErr = status;
- }
-
- #pragma mark -
- #pragma mark Format Routines
- static void FormatFloppyCompletion ( UInt32 userData, OSStatus status );
-
- OSStatus FormatFloppyDisk(FloppyRequestPB *drivePB)
- {
- UInt32 TotalBlocksOnMedia, BlockLengthInBytes;
- Boolean IsWriteProtected;
- OSType currentType;
-
- GetMediaProperties( &TotalBlocksOnMedia, &BlockLengthInBytes, &IsWriteProtected, ¤tType );
- return FormatMedia( (UInt32) drivePB,
- TotalBlocksOnMedia,
- BlockLengthInBytes,
- FormatFloppyCompletion );
- }
-
- void FormatFloppyCompletion( UInt32 userData,
- OSStatus status )
- {
- OSStatus err = status;
- DriveQRec *drive;
- FloppyRequestPB *drivePB = (FloppyRequestPB *) userData;
-
- drive = gFloppyDrive;
-
- if (err == noErr)
- {
- Boolean isWriteProtected;
- OSType currentType;
-
- GetMediaProperties( &drive->capacity, &drive->blockSize, &isWriteProtected, ¤tType );
- if ((drive->capacity == 0) || (drive->blockSize == 0))
- {
- // The format has failed, inform the OS
- err = controlErr;
- }
- }
- else
- {
- // The format has failed, inform the OS
- err = controlErr;
- }
-
- (*drivePB->completionProc)( drivePB->userData, err );
- }
-
-